package view.trajectory;

import java.util.ArrayList;
import java.util.Iterator;

import javax.media.opengl.GL;
import javax.media.opengl.GLAutoDrawable;

import mathematics.geometry.Geometry;
import mathematics.geometry.PolygonGeometry;
import model.RoomModel;
import model.path.Point4D;
import model.trajectory.BaseTrajectoryModel;
import model.trajectory.RoomTrajectoryModel;
import model.trajectory.TargetModel;
import model.trajectory.TransitionTrajectoryModel;

import colors.Color;

import utils.Pair;
import utils.Point3D;
import utils.TimeIntervalle;
import utils.Vector3D;
import view.RoomView;
import graphics.engine.ProgramShader;

import graphics.primitive.Polygon;
import graphics.primitive.Polyline;

public class TargetView {

	public TargetModel model;
	public TrajectoryView trajView;
	
	public PolygonGeometry geometry;
	
	public Polyline outline;
	public Polygon quad;
	public Color color;
	
	public float size = 50;
	public Point3D position;
	
	public TargetView(GL gl, TargetModel model, TrajectoryView traj)
	{	
		this.model = model;
		this.color = model.getColor();
		this.trajView = traj;
		
		geometry = new PolygonGeometry();
		geometry.add(new Point3D(0, - size / 2));
		geometry.add(new Point3D(- size / 2, 0));
		geometry.add(new Point3D(0, size / 2));
		geometry.add(new Point3D(size / 2, 0));
		geometry.setLoop(true);
		
		this.outline = new Polyline(gl, geometry,  1.0f);
		this.outline.setColor(this.color);
		
		this.quad = new Polygon(gl, geometry);
		this.quad.setColor(new Color(1.0f, 1.0f, 1.0f));
		
		this.position = new Point3D();
	}
	
	public void Draw(GLAutoDrawable drawable, ProgramShader programShader, long time)
	{
		this.setPosition(time);
		
		if(this.model.isVisible())
		{
			quad.Draw(drawable, programShader);
			outline.Draw(drawable, programShader);
		}
	}
	
	public void DrawTrajectory(GLAutoDrawable drawable, ProgramShader programShader, long logTime, long beginTime, long endTime)
	{
		if(this.model.isVisible())
		{
			this.trajView.Draw(drawable, programShader, logTime, beginTime, endTime);
		}
	}

	public void hasChanged(boolean value)
	{
		this.trajView.hasChanged(value);
	}
	
	public void setPosition(long time) 
	{
		Point3D result = new Point3D();
		
		for(Iterator<Pair<TimeIntervalle, BaseTrajectoryModel>> it = this.model.traj.subTrajectories.iterator(); it.hasNext(); )
		{
			Pair<TimeIntervalle, BaseTrajectoryModel> pair = it.next();
			TimeIntervalle intervalle = pair.key;
			BaseTrajectoryModel subTrajModel = pair.value;
			RoomModel referenceRoom;
			RoomView roomView;
			
			if(intervalle.include(time))
			{		
				if(subTrajModel.getClass() == RoomTrajectoryModel.class)
				{
					referenceRoom = ((RoomTrajectoryModel)subTrajModel).room;
				}
				else
				{
					referenceRoom = ((TransitionTrajectoryModel)subTrajModel).door.FirstRoom;
				}
				roomView = this.trajView.getRoomViewById(referenceRoom.getID());
				
				if(roomView.isNodeShape())
				{
					result = Point3D.sum(referenceRoom.getCenter(), Vector3D.mult(this.getPositionAroundNode(referenceRoom, time), roomView.nodeSize));	
			
					this.position = result;
					outline.setPosition(this.position);
					quad.setPosition(this.position);
					return;
				}
				else if(subTrajModel.getClass() == RoomTrajectoryModel.class)
				{
					Point4D lastPoint = null;
					for(Iterator<Point4D> itPoints = subTrajModel.positions.iterator(); itPoints.hasNext();)
					{
						Point4D currentPoint = itPoints.next();
					
						if(lastPoint != null)
						{					
							if(lastPoint.getTime().getTime() <= time && currentPoint.getTime().getTime() > time)
							{
								this.position = currentPoint;
								outline.setPosition(this.position);
								quad.setPosition(this.position);

								return;
							}
						}
						lastPoint = currentPoint;
					}
				}
			}
		}

	}
	
	
	public Vector3D getPositionAroundNode(RoomModel room, long time)
	{
		ArrayList<TargetModel> targets = room.targetsByTime(time); // new ArrayList(); //room.getTargetsInsideRoomByTime(time);
		
		float nbTargets = targets.size();
		if(nbTargets <= 1)
		{
			return new Vector3D();
		}
		
		int thisTargetIndex = 0;
		for(Iterator<TargetModel> it = targets.iterator(); it.hasNext(); )
		{
			TargetModel currentModel = it.next(); 
			if(currentModel.getID() == this.model.getID())
			{
				break;
			}
			thisTargetIndex++;
		}
		
		float angle = (float) (Math.PI * 2 / nbTargets);
		float x =  (float) Math.cos(angle * thisTargetIndex);
		float y =  (float) Math.sin(angle * thisTargetIndex);
		
		return  new Vector3D(x,y);
		//return point;
	}

	public boolean isIntersectedBy(Geometry geometry) {
		if(this.geometry.isIntersectedBy(geometry))
		{
			return true;
		}
		else if ( this.trajView.isIntersectedBy(geometry))
		{
			return true;
		}
		return false;
	}
}
